using System.Collections.Generic;
using UnityEngine;

namespace CHot
{
    public class ColliderGroup : MonoBehaviour
    {
        static List<HitListener> classPool = new List<HitListener>();
        static HitListener PopHitListener(ColliderGroup parent, ColliderGroup other)
        {
            HitListener hitListener = null;
            if (classPool.Count > 0)
            {
                hitListener = classPool[classPool.Count - 1];
                classPool.Remove(hitListener);
                hitListener.Init(parent, other);
                return hitListener;
            }
            hitListener = new HitListener();
            hitListener.Init(parent, other);
            return hitListener;
        }
        static void PushHitListener(HitListener hitListener)
        {
            if (hitListener != null)
            {
                hitListener.OnRecycle();
                classPool.Add(hitListener);
            }
        }

        class HitListener
        {
            public ColliderGroup parent;
            public uint stayFrame;
            public ColliderGroup other;
            public void Init(ColliderGroup parent, ColliderGroup other)
            {
                this.parent = parent;
                this.other = other;
                ColliderManager.Instance.HitEnter(parent, other);
            }

            public void OnRecycle()
            {
                this.parent = null;
                this.stayFrame = 0;
                this.other = null;
            }

            public void Keep()
            {
                stayFrame = 2;
            }

            public void Update()
            {
                ColliderManager.Instance.HitStay(parent, other);
                if (this.stayFrame > 0)
                {
                    this.stayFrame--;
                    if (this.stayFrame == 0)
                    {
                        parent.removeList.Add(other.instanceID);
                        ColliderManager.Instance.HitExit(parent, other);
                    }
                }
            }
        }

        public bool isFish = true;

        public bool showDebugLine;
        public Collider[] colliders;
        public bool isActive { get { return activeFrame > 0; } }
        public ColliderGroup lockTarget { get; set; }

        private int instanceID;
        private uint activeFrame;
        private Dictionary<int, HitListener> hitGroups = new Dictionary<int, HitListener>();
        private List<int> removeList = new List<int>();

        private void Awake()
        {
            for (int i = 0; i < colliders.Length; i++)
            {
                if (colliders[i] as BoxCollider)
                {
                    Debug.LogError("鱼碰撞不能使用 BoxCollider");
                }
            }
        }

        private void OnEnable()
        {
            lockTarget = null;
            instanceID = gameObject.GetInstanceID();
        }

        private void OnDisable()
        {
            activeFrame = 0;
            ColliderManager.Instance.Remove(this);
        }

        private void Update()
        {
            if (activeFrame == 0)
            {
                //对象生成时OnEnable时，位置可能仍然还在圆点，需等待一帧再进行初始化
                for (int i = 0; i < colliders.Length; i++)
                {
                    colliders[i].Init();
                }
                ColliderManager.Instance.Add(this);
                activeFrame++;
            }
        }

        //系统内部调用,判断碰撞的结束
        public void _OnExitListen()
        {
            foreach (var group in hitGroups.Values)
            {
                group.Update();
            }
            for (int i = 0; i < removeList.Count; i++)
            {
                int key = removeList[i];
                HitListener listener = hitGroups[key];
                hitGroups.Remove(key);
                PushHitListener(listener);
            }
            removeList.Clear();
        }

        //系统内部调用
        public void _OnHitListen(ColliderGroup other)
        {
            HitListener listener = null;
            if (!hitGroups.ContainsKey(other.instanceID))
            {
                listener = PopHitListener(this, other);
                hitGroups.Add(other.instanceID, listener);
            }
            else
            {
                listener = hitGroups[other.instanceID];
            }
            listener.Keep();
        }

#if UNITY_EDITOR
        void OnDrawGizmos()
        {
            if (showDebugLine && isActive)
            {
                Gizmos.color = Color.red;
                for (int i = 0; i < colliders.Length; i++)
                {
                    Collider collider = colliders[i];
                    if (collider is CircleCollider)
                    {
                        CircleCollider circleCollider = collider as CircleCollider;
                        Gizmos.DrawLine(circleCollider.lastPos, circleCollider.transform.position);
                    }
                }
            }
        }
#endif
    }
}